﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace XFFSM
{
    public class FSMController : MonoBehaviour
    {

        #region 字段

        [SerializeField]
        private List<RuntimeFSMController> _runtimeFSMController = new List<RuntimeFSMController>();
        #endregion

        #region 属性

        /// <summary>
        /// 当前状态机执行的状态配置文件列表
        /// </summary>
        public List<RuntimeFSMController> RuntimeFSMController
        {
            get
            {
                if (Application.isPlaying)
                {
                    return runtimeControllers;
                }

                return _runtimeFSMController;
            } 
        }
          
        internal object userData;

        private List<RuntimeFSMControllerInstance> Instances = new List<RuntimeFSMControllerInstance>();

        private List<RuntimeFSMController> runtimeControllers = new List<RuntimeFSMController>();

        #endregion

        #region 生命周期

        private void Start()
        {
            Init();
        }
        
        private void Update()
        {  
            foreach (var item in Instances)
            {
                item.Update();
            }
        }

        private void LateUpdate()
        { 
            foreach (var item in Instances)
            {
                item.LateUpdate();
            }
        }

        private void FixedUpdate()
        { 
            foreach (var item in Instances)
            {
                item.FixedUpdate();
            }
        }
         
        #endregion

        #region 方法

        // 初始化
        private void Init()
        {
            Instances.Clear();
            runtimeControllers.Clear();

            foreach (var item in _runtimeFSMController) 
            {
                if (item == null) continue;

                RuntimeFSMControllerInstance instance = new RuntimeFSMControllerInstance(item, this);
                instance.StartUp();
                runtimeControllers.Add(instance.RuntimeFSMController);
                Instances.Add(instance);
            } 
        }

        /// <summary>
        /// 设置bool类型参数的值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="v">值</param>
        public void SetBool(string name, bool v)
        { 
            foreach (var item in Instances)
            {
                item.SetBool(name, v);
            }
        }

        /// <summary>
        /// 设置float类型参数的值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="v">值</param>
        public void SetFloat(string name, float v)
        {
            foreach (var item in Instances)
            {
                item.SetFloat(name, v);
            }
        }

        /// <summary>
        /// 设置Int类型参数的值
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="v">值</param>
        public void SetInt(string name, int v)
        {
            foreach (var item in Instances)
            {
                item.SetInt(name, v);
            }
        }

        /// <summary>
        /// 触发Trigger
        /// </summary>
        /// <param name="name">Trigger名称</param>
        public void SetTrigger(string name) {
            foreach (var item in Instances)
            {
                item.SetTrigger(name);
            }
        }

        /// <summary>
        /// 还原Trigger
        /// </summary>
        /// <param name="name">Trigger名称</param>
        public void ResetTrigger(string name) {
            foreach (var item in Instances)
            {
                item.ResetTrigger(name);
            }
        }

        /// <summary>
        /// 运行时添加并执行状态配置文件
        /// </summary>
        /// <param name="controller"></param>
        public void AddRuntimeFSMController(RuntimeFSMController controller) {
            if (_runtimeFSMController.Contains(controller))
            {
                Debug.LogWarningFormat("状态机:{0}已经执行,请勿重复添加!", controller.name);
                return; // 说明已经添加了该状态机
            }
            _runtimeFSMController.Add(controller);

            RuntimeFSMControllerInstance controllerInstance = new RuntimeFSMControllerInstance(controller, this);
            controllerInstance.StartUp();
            runtimeControllers.Add(controllerInstance.RuntimeFSMController);
            Instances.Add(controllerInstance);
        }

        /// <summary>
        /// 运行时移除状态机配置文件
        /// </summary>
        /// <param name="index">配置文件下标</param>
        public void RemoveRuntimeFSMController(int index) {
            if (index < 0 || index >= RuntimeFSMController.Count) return;
            RuntimeFSMController controller = RuntimeFSMController[index];
            RuntimeFSMController.RemoveAt(index);

            for (int i = 0; i < Instances.Count; i++)
            {
                if (Instances[i].RuntimeFSMController == controller) 
                {
                    Instances[i].Close();
                    Instances.Remove(Instances[i]);
                    break;
                }
            }
        }

        /// <summary>
        /// 获取当前正在执行的状态信息
        /// </summary>
        /// <param name="index">状态配置下标</param>
        /// <returns></returns>
        public FSMStateNode GetCurrentStateInfo(int index)
        {
            if (index < 0 || index >= Instances.Count) return null;
            return Instances[index].currentState;
        }

        /// <summary>
        /// 获取当前的状态切换信息
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public FSMTransition GetCurrentTransition(int index) 
        {
            if (index < 0 || index >= Instances.Count) return null;
            return Instances[index].currentTransition; 
        }

        #endregion

        #region 静态字段

        private static Dictionary<string,FSMController> fsms = new Dictionary<string,FSMController>();

        #endregion

        #region 静态属性

        private static Transform _FSMParent;

        private static Transform FSMParent
        {
            get {
                if (_FSMParent == null) 
                {
                    GameObject obj = new GameObject("FSMControllers");
                    DontDestroyOnLoad(obj);
                    _FSMParent = obj.transform;
                }

                return _FSMParent;
            }
        }

        #endregion

        #region 静态方法

        /// <summary>
        /// 启动状态(适用于没有具体游戏物体的状态管理,例如:游戏状态)
        /// </summary>
        /// <param name="fsmName">状态机名称</param>
        /// <param name="fsm">状态配置文件</param>
        /// <param name="userData">自定义参数或数据</param>
        /// <returns></returns>
        public static FSMController StartupFSM(string fsmName,RuntimeFSMController fsm,object userData = null)
        {
            if (fsms.ContainsKey(fsmName)) return null;
            GameObject obj = new GameObject(fsmName);
            obj.transform.SetParent(FSMParent,false);
            FSMController controller = obj.AddComponent<FSMController>();
            controller.userData = userData;
            controller.AddRuntimeFSMController(fsm);
            fsms.Add(fsmName, controller);
            return controller;
        }

        /// <summary>
        /// 查询通过FSMController.StartupFSM启动的状态机
        /// </summary>
        /// <param name="fsmName">状态机名称</param>
        /// <returns></returns>
        public static FSMController GetFSM(string fsmName)
        {
            if(fsms.ContainsKey(fsmName)) 
                return fsms[fsmName];
            return null;
        }

        /// <summary>
        /// 移除通过FSMController.StartupFSM启动的状态机
        /// </summary>
        /// <param name="fsmName">状态机名称</param>
        public static void RemoveFSM(string fsmName)
        {
            if (!fsms.ContainsKey(fsmName)) return;
            FSMController controller = fsms[fsmName];
            fsms.Remove(fsmName);
            Destroy(controller.gameObject);
        }

        #endregion

    }

}

